#include "stdafx.h"
#include "image_type.h"

uint_32 align_to_2(uint_32 val)
{
	if(val & 0x1)
		return val + 1;
	else
		return val;
}
uint_32 align_to_4(uint_32 val)
{
	if(val & 0x3)
		return (val & (~0x3)) + 0x4;
	else
		return val;
}
uint_8 color_float16_to_8(uint_16 f16)
{
	union
	{
		int_32 ival;
		float_32 fval;
	};

	int_32 signific = (f16 >> 15) & 0x1;
	int_32 exponent = (f16 >> 10) & 0x1F;
	int_32 mantissa = (f16 & 0x3FF);

	if(mantissa == 0)
		return 0xFF;
	else if(exponent == 0)
	{
		while(!(mantissa & 0x00000400))
		{
			mantissa <<= 1;
			exponent -=  1;
		}

		exponent += 1;
		mantissa &= ~0x00000400;
	}
	else if(exponent == 31)
	{
		ival = (signific << 31) | 0x7f800000 | (mantissa << 13);
	}
	else
	{
		exponent += 0x70;
		ival = (signific << 31) | (exponent << 23) | (mantissa << 13);
	}
	//if(fval < 0.0f)
	//	return 0;
	//else if(fval > 1.0f)
	//	return 0xFF;
	//else
	return (uint_8)(fval * 0xFF);
} 

color_mode_e color_mode_from_mask_abgr(color_mask_abgr_t * mask, uint_32 bits)
{
	switch(bits)
	{
	case 8:
		break;
	case 16:
		if(mask->r == X4R4G4B4_R_MASK &&
			mask->g == X4R4G4B4_G_MASK && mask->b == X4R4G4B4_B_MASK)
		{
			if(mask->a == 0)
				return color_mode_x4r4g4b4;
			else if(mask->a = X4R4G4B4_A_MASK)
				return color_mode_a4r4g4b4;
			else {}
		}
		else if(mask->r == R5G6B5_R_MASK &&
			mask->g == R5G6B5_G_MASK && mask->b == R5G6B5_B_MASK)
		{
			return color_mode_r5g6b5;
		}
		else if(mask->r == X1R5G5B5_R_MASK &&
			mask->g == X1R5G5B5_G_MASK && mask->b == X1R5G5B5_B_MASK)
		{
			if(mask->a == 0)
				return color_mode_x1r5g5b5;
			else if(mask->a == X1R5G5B5_A_MASK)
				return color_mode_a1r5g5b5;
			else {}
		}
		else {}
		break;
	case 24:
		if(mask->r == X8R8G8B8_R_MASK &&
			mask->g == X8R8G8B8_G_MASK && mask->b == X8R8G8B8_B_MASK)
		{
			if(mask->a == 0)
				return color_mode_r8g8b8;
			else {}
		}
		else if(mask->r == X8R8G8B8_B_MASK && mask->g == X8R8G8B8_G_MASK &&
			mask->b == X8R8G8B8_R_MASK)
		{
			if(mask->a == 0)
				return color_mode_b8g8r8;
		}
		else {}
		break;
	case 32:
		if(mask->r == X8R8G8B8_R_MASK &&
			mask->g == X8R8G8B8_G_MASK && mask->b == X8R8G8B8_B_MASK)
		{
			if(mask->a == 0)
				return color_mode_x8r8g8b8;
			else if(mask->a = X8R8G8B8_A_MASK)
				return color_mode_a8r8g8b8;
			else {}
		}
		else if(mask->r == R8G8B8X8_R_MASK && mask->g == R8G8B8X8_G_MASK &&
			mask->b == R8G8B8X8_B_MASK)
		{
			if(mask->a == 0)
				return color_mode_r8g8b8x8;
			else if(mask->a == R8G8B8X8_A_MASK)
				return color_mode_r8g8b8a8;
			else {}
		}
		else if(mask->r == G16R16_R_MASK && mask->g == G16R16_G_MASK)
		{
			if(mask->a == 0 && mask->b == 0)
				return color_mode_g16r16;
			else {}
		}
		else if(mask->r == X8R8G8B8_B_MASK && mask->g == X8R8G8B8_G_MASK &&
			mask->b == X8R8G8B8_R_MASK)
		{
			if(mask->a == 0)
				return color_mode_x8b8g8r8;
			else if(mask->a == X8R8G8B8_A_MASK)
				return color_mode_a8b8g8r8;
			else {}
		}
		else {}
		break;
	}
	return color_mode_invalid;
}



//////////////////////////////////////////////////////////////////////////
/// color_a_to_b

void color_8_to_8(void * src_pixel, void * dst_pixel)
{
	uint_8 * src = (uint_8 *)src_pixel;
	uint_8 * dst = (uint_8 *)dst_pixel;
	*dst = *src;
}

void color_16_to_16(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	uint_16 * dst = (uint_16 *)dst_pixel;
	*dst = *src;
}

void color_24_to_24(void * src_pixel, void * dst_pixel)
{
	color_rgb_t * src = (color_rgb_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	*dst = *src;
}

void color_32_to_32(void * src_pixel, void * dst_pixel)
{
	uint_32 * src = (uint_32 *)src_pixel;
	uint_32 * dst = (uint_32 *)dst_pixel;
	*dst = *src;
}

void color_r8g8b8x8_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_rgba_t * src = (color_rgba_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	*dst = src->rgb;
}

void color_x4r4g4b4_to_x1r5g5b5(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	uint_16 * dst = (uint_16 *)dst_pixel;
	*dst = 
		((*src & X4R4G4B4_R_MASK) << 3) |
		((*src & X4R4G4B4_G_MASK) << 2) |
		((*src & X4R4G4B4_B_MASK) << 1);
}

void color_r5g6b5_to_x1r5g5b5(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	uint_16 * dst = (uint_16 *)dst_pixel;
	*dst = 
		((*src & R5G6B5_R_MASK) >> 1) |
		(((*src & R5G6B5_G_MASK) >> 1) & X1R5G5B5_G_MASK) |
		((*src & R5G6B5_B_MASK));
}
void color_r5g6b5_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;

	dst->r = uint_8((*src & R5G6B5_R_MASK) >> 8);
	dst->g = uint_8((*src & R5G6B5_G_MASK) >> 3);
	dst->b = uint_8((*src & R5G6B5_B_MASK) << 3);
}

void color_r5g6b5_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;

	dst->r = uint_8((*src & R5G6B5_R_MASK) >> 8);
	dst->g = uint_8((*src & R5G6B5_G_MASK) >> 3);
	dst->b = uint_8((*src & R5G6B5_B_MASK) << 3);
	dst->a = 0xFF;
}

void color_a1r5g5b5_to_x1r5g5b5(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	uint_16 * dst = (uint_16 *)dst_pixel;
	*dst = *src | X1R5G5B5_A_MASK;
}
void color_a1r5g5b5_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;
	dst->a = uint_8((*src & X1R5G5B5_A_MASK) >> 8);
	dst->r = uint_8((*src & X1R5G5B5_R_MASK) >> 7);
	dst->g = uint_8((*src & X1R5G5B5_G_MASK) >> 2);
	dst->b = uint_8((*src & X1R5G5B5_B_MASK) << 3);
}
void color_a4r4g4b4_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;
	dst->a = uint_8((*src & X4R4G4B4_A_MASK) >> 8);
	dst->r = uint_8((*src & X4R4G4B4_R_MASK) >> 4);
	dst->g = uint_8(*src & X4R4G4B4_G_MASK);
	dst->b = uint_8((*src & X4R4G4B4_B_MASK) << 4);
}
void color_a16b16g16r16_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_a16b16g16r16_t * src = (color_a16b16g16r16_t *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;
	dst->a = src->a >> 8;
	dst->r = src->r >> 8;
	dst->g = src->g >> 8;
	dst->b = src->b >> 8;
}
void color_a16b16g16r16f_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_a16b16g16r16f_t * src = (color_a16b16g16r16f_t *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;
	dst->a = color_float16_to_8(src->a);
	dst->r = color_float16_to_8(src->r);
	dst->g = color_float16_to_8(src->g);
	dst->b = color_float16_to_8(src->b);
}
void color_g16r16_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_32 * src = (uint_32 *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	dst->r = (*src & G16R16_R_MASK) >> 8;
	dst->g = (*src & G16R16_G_MASK) >> 24;
	dst->b = 0xFF;
}
void color_g16r16f_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_g16r16f_t * src = (color_g16r16f_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	dst->r = color_float16_to_8(src->r);
	dst->g = color_float16_to_8(src->g);
	dst->b = 0xFF;
}
void color_r16f_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_16 * src = (uint_16 *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	dst->r = color_float16_to_8(*src);
	dst->g = 0xFF;
	dst->b = 0xFF;
}
void color_r32f_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	float_32 * src = (float_32 *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	dst->r = uint_8(*src * 255.0f);
	dst->g = 0xFF;
	dst->b = 0xFF;
}
void color_g32r32f_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_g32r32f_t * src = (color_g32r32f_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	dst->r = uint_8(src->r * 255.0f);
	dst->g = uint_8(src->g * 255.0f);
	dst->b = 0xFF;
}
void color_a32b32g32r32f_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_a32b32g32r32f_t * src = (color_a32b32g32r32f_t *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;
	dst->a = uint_8(src->a * 255.0f);
	dst->r = uint_8(src->r * 255.0f);
	dst->g = uint_8(src->g * 255.0f);
	dst->b = uint_8(src->b * 255.0f);
}

void color_r8g8b8_to_b8g8r8(void * src_pixel, void * dst_pixel)
{
	color_rgb_t * src = (color_rgb_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	dst->r = src->b;
	dst->g = src->g;
	dst->b = src->r;
}

void color_r8g8b8_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_rgb_t * src = (color_rgb_t *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;
	dst->a = 0xFF;
	dst->rgb = *src;
}

void color_a8r8g8b8_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_argb_t * src = (color_argb_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	*dst = src->rgb;
}
void color_a8b8g8r8_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_argb_t * src = (color_argb_t *)src_pixel;
	color_argb_t * dst = (color_argb_t *)dst_pixel;
	dst->a = src->a;
	dst->r = src->b;
	dst->g = src->g;
	dst->b = src->r;
}
void color_x8b8g8r8_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_argb_t * src = (color_argb_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;
	dst->r = src->b;
	dst->g = src->g;
	dst->b = src->r;
}

void color_gray8_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_rgb_t * dst_rgb = (color_rgb_t *)dst_pixel;
	uint_8 val = *((uint_8 *)src_pixel);
	dst_rgb->r = val;
	dst_rgb->g = val;
	dst_rgb->b = val;
}

void color_x1r5g5b5_r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_16 src_rgb = *((uint_16 *)src_pixel);
	color_rgb_t * dst_rgb = (color_rgb_t *)dst_pixel;
	dst_rgb->r = uint_8((src_rgb & 0x7C00) >> 7);
	dst_rgb->g = uint_8((src_rgb & 0x3E0) >> 2);
	dst_rgb->b = uint_8((src_rgb & 0x1F) << 3);
}

void color_a8r8g8b8_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_argb_t * src_argb = (color_argb_t *)src_pixel;
	color_argb_t * dst_argb = (color_argb_t *)dst_pixel;
	*dst_argb = *src_argb;
}

void color_yuv_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_yuv_t * yuv = (color_yuv_t *)src_pixel;
	color_rgb_t * rgb = (color_rgb_t *)dst_pixel;
	int_32 temp = 0;

	temp = (int_32)(yuv->y + 1.402f * (yuv->v - 128) + 0.03125f);
	if(temp < 0)
		rgb->r = 0;
	else if(temp > 0xFF)
		rgb->r = 0xFF;
	else
		rgb->r = (uint_8)temp;

	temp = (int_32)(yuv->y - 0.34413f * (yuv->u - 128) - 0.71414f * (yuv->v - 128));
	if(temp < 0)
		rgb->g = 0;
	else if(temp > 0xFF)
		rgb->g = 0xFF;
	else
		rgb->g = (uint_8)temp;

	temp = (int_32)(yuv->y + 1.772f * (yuv->u - 128));
	if(temp < 0)
		rgb->b = 0;
	else if(temp > 0xFF)
		rgb->b = 0xFF;
	else
		rgb->b = (uint_8)temp;
}

void color_r8g8b8_to_yuv(void * src_pixel, void * dst_pixel)
{
	color_rgb_t * src = (color_rgb_t *)src_pixel;
	color_yuv_t * dst = (color_yuv_t *)dst_pixel;
	dst->y = uint_8(0.299f * src->r + 0.587f * src->g + 0.114f * src->b);
	dst->u = uint_8(0.169 * src->r - 0.3313f * src->g + 0.5f * src->b);
	dst->v = uint_8(0.5f * src->r - 0.4187f * src->g - 0.0813f * src->b);
}

void color_yuv_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_yuv_t * yuv = (color_yuv_t *)src_pixel;
	color_argb_t * argb = (color_argb_t *)dst_pixel;
	argb->a = 0xFF;
	color_yuv_to_r8g8b8(yuv, (color_rgb_t *)argb);
}

void color_ycck_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_ycck_t * ycck = (color_ycck_t *)src_pixel;
	color_rgb_t * rgb = (color_rgb_t *)dst_pixel;
	int_32 temp = 0;

	temp = (int_32)(ycck->y + 1.402f * (ycck->r - 128) + 0.03125f);
	if(temp < 0)
		rgb->r = 0;
	else if(temp > 0xFF)
		rgb->r = 0xFF;
	else
		rgb->r = (uint_8)temp;

	temp = (int_32)(ycck->y - 0.34413f * (ycck->b - 128) - 0.71414f * (ycck->r - 128));
	if(temp < 0)
		rgb->g = 0;
	else if(temp > 0xFF)
		rgb->g = 0xFF;
	else
		rgb->g = (uint_8)temp;

	temp = (int_32)(ycck->y + 1.772f * (ycck->b - 128));
	if(temp < 0)
		rgb->b = 0;
	else if(temp > 0xFF)
		rgb->b = 0xFF;
	else
		rgb->b = (uint_8)temp;
}

void color_ycck_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_ycck_t * ycck = (color_ycck_t *)src_pixel;
	color_argb_t * argb = (color_argb_t *)dst_pixel;
	argb->a = 0xFF;
	color_ycck_to_r8g8b8(ycck, (color_rgb_t *)argb);
}

void color_gray_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_8 * gray = (uint_8 *)src_pixel;
	color_rgb_t * rgb = (color_rgb_t *)dst_pixel;
	rgb->r = *gray;
	rgb->g = *gray;
	rgb->b = *gray;
}

void color_gray_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	uint_8 * gray = (uint_8 *)src_pixel;
	color_argb_t * argb = (color_argb_t *)dst_pixel;
	argb->a = 0xFF;
	argb->r = *gray;
	argb->g = *gray;
	argb->b = *gray;
}

void color_cmyk_to_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_cmyk_t * cmyk = (color_cmyk_t *)src_pixel;
	color_rgb_t * rgb = (color_rgb_t *)dst_pixel;
	rgb->r = (cmyk->k * cmyk->c) >> 8;
	rgb->g = (cmyk->k * cmyk->m) >> 8;
	rgb->b = (cmyk->k * cmyk->y) >> 8;
}

void color_cmyk_to_a8r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_cmyk_t * cmyk = (color_cmyk_t *)src_pixel;
	color_argb_t * argb = (color_argb_t *)dst_pixel;
	argb->a = 0xFF;
	color_cmyk_to_r8g8b8(cmyk, (color_rgb_t *)argb);
}

void color_r8g8b8_to_x32y32z32f(void * src_pixel, void * dst_pixel)
{
	color_rgb_t * src = (color_rgb_t *)src_pixel;
	color_x32y32z32f_t * dst = (color_x32y32z32f_t *)dst_pixel;

	float_32 r = src->r / 255.0f;
	float_32 g = src->g / 255.0f;
	float_32 b = src->b / 255.0f;

	dst->x = 0.412453f * r + 0.357580f * g + 0.180423f * b;  
	dst->y = 0.212671f * r + 0.715160f * g + 0.072169f * b;  
	dst->z = 0.019334f * r + 0.119193f * g + 0.950227f * b;
}

void colo_x32y32z32f_tor_r8g8b8(void * src_pixel, void * dst_pixel)
{
	color_x32y32z32f_t * src = (color_x32y32z32f_t *)src_pixel;
	color_rgb_t * dst = (color_rgb_t *)dst_pixel;

	float_32 r = 3.240479f * src->x  - 1.537150f * src->y - 0.498535f * src->z;  
	float_32 g = -0.969256f * src->x + 1.875992f * src->y + 0.041556f * src->z;  
	float_32 b = 0.055648f * src->x  - 0.204043f * src->y + 1.057311f * src->z; 

	if(r <= 0.0f)		dst->r = 0;
	else if(r >= 1.0f)	dst->r = 0xFF;
	else				dst->r = uint_8(r * 0xFF);

	if(g <= 0.0f)		dst->g = 0;
	else if(g >= 1.0f)	dst->g = 0xFF;
	else				dst->g = uint_8(g * 0xFF);

	if(b <= 0.0f)		dst->b = 0;
	else if(r >= 1.0f)	dst->b = 0xFF;
	else				dst->b = uint_8(b * 0xFF);
}
